package com.nova.bluetooth.xunFeiSDK.mainFunction;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ScrollView;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.iflytek.aiui.AIUIAgent;
import com.iflytek.aiui.AIUIConstant;
import com.iflytek.aiui.AIUIListener;
import com.nova.bluetooth.R;
import com.nova.bluetooth.xunFeiSDK.engine.AiuiEngine;
import com.nova.bluetooth.xunFeiSDK.engine.EngineConstants;
import com.nova.bluetooth.xunFeiSDK.recorder.AudioRecorder;
import com.nova.bluetooth.xunFeiSDK.recorder.RecorderFactory;
import com.nova.bluetooth.xunFeiSDK.recorder.SystemRecorder;
import com.nova.bluetooth.xunFeiSDK.utils.CopyAssetsUtils;
import com.nova.bluetooth.xunFeiSDK.utils.ErrorCode;
import com.nova.bluetooth.xunFeiSDK.utils.FileUtil;
import com.nova.bluetooth.xunFeiSDK.utils.StreamingAsrUtil;
import com.nova.bluetooth.xunFeiSDK.utils.senselessWordUtil;


import java.nio.charset.StandardCharsets;

public class AsrActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = AsrActivity.class.getSimpleName();
    Handler handler = new Handler();
    private TextView mResText;
    private ScrollView mScrollView;
    private Button btnAsrResult;
    // AIUI
    private AIUIAgent mAIUIAgent;
    private AudioRecorder recorder;

    /**
     * AIUI 回调信息处理
     */
    private AIUIListener aiuiListener = event -> {
        switch (event.eventType) {
            case AIUIConstant.EVENT_CONNECTED_TO_SERVER:
                String uid = event.data.getString("uid");
                Log.i(TAG, "已连接服务器,uid：" + uid);
                break;

            case AIUIConstant.EVENT_SERVER_DISCONNECTED:
                Log.i(TAG, "与服务器断开连接");
                break;

            case AIUIConstant.EVENT_WAKEUP:
                Log.i(TAG, "进入识别状态");
                break;

            case AIUIConstant.EVENT_RESULT:
                //处理语音合成结果
                if (event.info.contains("\"sub\":\"tts")) {
                    //无意义词不处理
                    if (event.data.getString("sid").equals(senselessWordUtil.nonsenseSid)) {
                        AiuiEngine.TTS_stop();
                        return;
                    }
                    //保存云端的tts音频文件，用于离线播放
                    if (EngineConstants.saveTTS) {
                        byte[] audio = event.data.getByteArray("0"); //tts音频数据，16k，16bit格式
                        FileUtil.writeFile(audio, "/sdcard/tts.pcm");
                    }

                    //如果使用sdk的播放器合成，可以不用解析tts
                    return;

                    //开发者自己用播放器来合成
//                    byte[] audio=event.data.getByteArray("0");//tts音频数据，16k，16bit格式
//                    超过500ms静音，认为是无效音频，进行过滤
//                    byte[] filteredAudio= TtsFilterUtil.filter(audio,500);
                }
                //处理识别结果
                if (event.info.contains("\"sub\":\"iat")) {
                    JSONObject cntJson = JSON.parseObject(new String(event.data.getByteArray("0"), StandardCharsets.UTF_8));
                    if (cntJson == null) {
                        return;
                    }
                    JSONObject text = cntJson.getJSONObject("text");
                    //识别结果
                    String asrResult = StreamingAsrUtil.processIATResult(text);
                    btnAsrResult.setText(asrResult);
                }
                //处理语义结果
                else if (event.info.contains("\"sub\":\"nlp")) {
                    JSONObject cntJson = JSON.parseObject(new String(event.data.getByteArray("0"), StandardCharsets.UTF_8));
                    JSONObject nlpResult = cntJson.getJSONObject("intent");
                    //nlp无结果不处理
                    if (nlpResult.isEmpty()) {
                        return;
                    }
                    //如果只判断asr结果中的无意义词，若nlp先返回就可能被错误判断为无意义词
                    String asrResult = nlpResult.getString("text");
                    EngineConstants.meaningful = senselessWordUtil.isMeaningful_filter1word(asrResult);
                    //无意义词不处理
                    if (!EngineConstants.meaningful) {
                        senselessWordUtil.nonsenseSid = event.data.getString("sid");
                        Log.i(TAG, "无意义请求的sid=" + senselessWordUtil.nonsenseSid);
                        return;
                    }
                    Log.i(TAG, "nlp result :" + nlpResult);
                    //在线语义结果,rc=0语义理解成功，rc≠0语义理解失败
                    setText(nlpResult.toString());
                }
                break;

            case AIUIConstant.EVENT_ERROR:
                setText("错误码: " + event.arg1);
                setText("错误信息:" + event.info);
                setText("解决方案:" + ErrorCode.getError(event.arg1) + "\n  错误解决详情参考：https://www.yuque.com/iflyaiui/zzoolv/igbuol");
                break;

            case AIUIConstant.EVENT_VAD:
                if (AIUIConstant.VAD_BOS == event.arg1) {
                    Log.i(TAG, "开始说话 vad_bos");
                } else if (AIUIConstant.VAD_BOS_TIMEOUT == event.arg1) {
                    Log.i(TAG, "长时间不说话,前端点超时");
                } else if (AIUIConstant.VAD_EOS == event.arg1) {
                    Log.i(TAG, "结束说话 vad_eos");
                } else if (AIUIConstant.VAD_VOL == event.arg1) {
                    //回调太多，一般情况下可以注释掉
//                    Log.i(TAG, "vad vol,说话音量:" + event.arg2);
                }
                break;
            case AIUIConstant.EVENT_SLEEP:
                Log.i(TAG, "设备休眠");
                break;

            case AIUIConstant.EVENT_START_RECORD:
                Log.i(TAG, "开始录音");
                break;

            case AIUIConstant.EVENT_STOP_RECORD:
                stopRecord();
                break;

            case AIUIConstant.EVENT_STATE:    // 状态事件
                EngineConstants.mAIUIState = event.arg1;
                if (AIUIConstant.STATE_IDLE == EngineConstants.mAIUIState) {
                    // 闲置状态，AIUI未开启
                    Log.i(TAG, "aiui状态:STATE_IDLE");
                } else if (AIUIConstant.STATE_READY == EngineConstants.mAIUIState) {
                    // AIUI已就绪，等待唤醒
                    Log.i(TAG, "aiui状态:STATE_READY");
                } else if (AIUIConstant.STATE_WORKING == EngineConstants.mAIUIState) {
                    // AIUI工作中，可进行交互
                    Log.i(TAG, "aiui状态:STATE_WORKING");
                }
                break;

            default:
                break;
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_asr);
        initLayout();
        // 资源拷贝
        CopyAssetsUtils.portingFile(this);
    }

    private void initLayout() {
        findViewById(R.id.init_sdk).setOnClickListener(this);
        findViewById(R.id.btnStartRecord).setOnClickListener(this);
        findViewById(R.id.btnStopRecord).setOnClickListener(this);
        findViewById(R.id.btnSave).setOnClickListener(this);
        TextView titleTextView = findViewById(R.id.myTitle);
        titleTextView.setText("AIUI(识别)");
        ((Button) findViewById(R.id.btnStopRecord)).setText("停止录音");
        mScrollView = findViewById(R.id.scrollView);
        mResText = findViewById(R.id.res_text);
        btnAsrResult = findViewById(R.id.btnSave);

        btnAsrResult.setText("流式识别结果：");
        mResText.append("默认单轮交互（点击一次交互一次），在aiui.cfg修改oneshot为continuous实现多轮交互 \n");
    }

    @Override
    public void onClick(View view) {
        int id = view.getId();
        if (id == R.id.init_sdk) {
            initSDK();
        } else if (id == R.id.btnStartRecord) {
            startRecord();
        } else if (id == R.id.btnStopRecord) {
            stopRecord();
        }
    }

    private void initSDK() {
        //状态初始化
        EngineConstants.isRecording = false;
        //TODO 开发者需要实现生成sn的代码，参考：https://www.yuque.com/iflyaiui/zzoolv/tgftb5
        //注意事项1: sn每台设备需要唯一！！！！WakeupEngine的sn和AIUI的sn要一致
        //注意事项2: 获取的值要保持稳定，否则会重复授权，浪费授权量
        EngineConstants.serialNumber = "iflytek-test";
        // 初始化AIUI(识别+语义+合成）
        mAIUIAgent = AiuiEngine.getInstance(aiuiListener);
        if (mAIUIAgent != null) {
            setText("AIUI初始化成功");
        } else {
            setText("AIUI初始化失败");
        }

        //对音频的处理为不降噪唤醒直接送去识别，只保留1声道音频,
        SystemRecorder.AUDIO_TYPE_ASR = true;
        //初始化录音
        //初始化录音
        if (recorder == null) {
            recorder= RecorderFactory.getRecorder();
        }

        if (recorder != null) {
            setText("录音机初始化成功");
        } else {
            setText("录音机初始化失败");
        }
    }


    private void startRecord() {
        if (recorder != null) {
            int ret = recorder.startRecord();
            if (0 == ret) {
                setText("开启录音成功！");
            } else if (111111 == ret) {
                setText("异常,AlsaRecorder is null ...");
            } else {
                setText("开启录音失败，请查看/dev/snd/下的设备节点是否有777权限！\nAndroid 8.0 以上需要暂时使用setenforce 0 命令关闭Selinux权限！");
                destroyRecord();
            }
        }
    }

    private void stopRecord() {
        if (recorder != null) {
            recorder.stopRecord();
            setText("停止录音");
        }
    }

    private void destroyRecord() {
        stopRecord();
        recorder = null;
        Log.d(TAG, "destroy is Done!");
    }

    /**
     * 根据scrollView 和子view去测量滑动的位置
     *
     * @param scrollView
     * @param view
     */
    private void scrollToBottom(final ScrollView scrollView, final View view) {

        handler.post(() -> {
            if (scrollView == null || view == null) {
                return;
            }
            // offset偏移量。是指当textview中内容超出 scrollview的高度，那么超出部分就是偏移量
            int offset = view.getMeasuredHeight()
                    - scrollView.getMeasuredHeight();
            if (offset < 0) {
                offset = 0;
            }
            //scrollview开始滚动
            scrollView.scrollTo(0, offset);
        });
    }

    //打印到屏幕
    private void setText(final String str) {
        if (Looper.getMainLooper() == Looper.myLooper()) {
            mResText.append(str + " \n");
            scrollToBottom(mScrollView, mResText);
        } else {
            runOnUiThread(() -> {
                mResText.append(str + " \n");
                scrollToBottom(mScrollView, mResText);
            });
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (EngineConstants.isRecording) {
            stopRecord();
        }
        if (recorder != null) {
            recorder.destroyRecord();
            recorder = null;
        }
        if (aiuiListener != null) {
            aiuiListener = null;
        }
        //销毁aiui
        AiuiEngine.destroy();
    }
}